package IC.Parser;
import java_cup.runtime.Symbol;



%%

%class Lexer
%public
%function next_token
%type Token
%line
%column
%scanerror LexicalError
%cup
%{
	private boolean isInCommentTag = false;
%}
%state COMMENT_LINE
%state COMMENTS
%eofval{
	if (isInCommentTag) {
		isInCommentTag = false;
		throw new LexicalError(yyline, yycolumn, "Comment not closed");
	}
	return new Token(sym.EOF,yyline);
%eofval}

LineTerminator=\r|\n|\r\n
WhiteSpace={LineTerminator} | [ \t\f]

ALPHA=[A-Za-z_]
DIGIT=[0-9]
ALPHA_NUMERIC={ALPHA}|{DIGIT}
IDENT=[a-z]({ALPHA_NUMERIC})*
NUMBER=({DIGIT})+
CLASSIDENT=[A-Z]({ALPHA_NUMERIC})*
INTEGER_LITERAL=(0|[1-9]({NUMBER})*)
PRINTABLE_ASCII_CHARS=[\x20-\x7E]
PRINTABLE_ASCII_CHARS_NO_GERSHAIM_NO_BACKSLASH=[ !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\]\^_`abcdefghijklmnopqrstuvwxyz{|}~]
ILLEGAL_PRINTABLE_CHARS_AFTER_NUMBER=[#$'(.:?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\^_`abcdefghijklmnopqrstuvwxyz{|}~]
ILLEGAL_CHARS_AFTER_NUMBER=({STRING_ESCAPE_CHARS}|{ILLEGAL_PRINTABLE_CHARS_AFTER_NUMBER})
STRING_ESCAPE_CHARS="\\\""|"\\\\"|"\\n"|[\x09\x0A]
STRING_LITERAL="\""({STRING_ESCAPE_CHARS}|{PRINTABLE_ASCII_CHARS_NO_GERSHAIM_NO_BACKSLASH})*"\""
ALL=.|\n
IDENT_ILLEGAL = {NUMBER}+({ILLEGAL_CHARS_AFTER_NUMBER})+({NUMBER})*

%%

<YYINITIAL> "//" { yybegin(COMMENT_LINE);  }
<COMMENT_LINE> \n { yybegin(YYINITIAL); }
<COMMENT_LINE> . { }


<YYINITIAL> "/*" {  isInCommentTag = true; yybegin(COMMENTS); }
<COMMENTS> "*/" {isInCommentTag = false; yybegin(YYINITIAL); }
<COMMENTS> {ALL} { } 


<YYINITIAL> "<=" {return new Token(sym.LTE,yyline);}
<YYINITIAL> "<" {return new Token(sym.LT,yyline);}
<YYINITIAL> ">=" {return new Token(sym.GTE,yyline);}
<YYINITIAL> ">" {return new Token(sym.GT,yyline);}
<YYINITIAL> "!=" {return new Token(sym.NEQUAL,yyline);}
<YYINITIAL> "!" {return new Token(sym.LNEG,yyline);}
<YYINITIAL> "==" {return new Token(sym.EQUAL,yyline);}
<YYINITIAL> "=" {return new Token(sym.ASSIGN,yyline);}
<YYINITIAL> "boolean" {return new Token(sym.BOOLEAN,yyline);}
<YYINITIAL> "break" {return new Token(sym.BREAK,yyline);}
<YYINITIAL> "class" {return new Token(sym.CLASS,yyline);}
<YYINITIAL> "," {return new Token(sym.COMMA,yyline);}
<YYINITIAL> "continue" {return new Token(sym.CONTINUE,yyline);}
<YYINITIAL> "/" {return new Token(sym.DIVIDE,yyline);}
<YYINITIAL> "." {return new Token(sym.DOT,yyline);}
<YYINITIAL> "extends" {return new Token(sym.EXTENDS,yyline);}
<YYINITIAL> "else" {return new Token(sym.ELSE,yyline);}
<YYINITIAL> "false" {return new Token(sym.FALSE,yyline);}
<YYINITIAL> "if" {return new Token(sym.IF,yyline);}
<YYINITIAL> "int" {return new Token(sym.INT,yyline);}
<YYINITIAL> "&&" {return new Token(sym.LAND,yyline);}
<YYINITIAL> "[" {return new Token(sym.LB,yyline);}
<YYINITIAL> "(" {return new Token(sym.LP,yyline);}
<YYINITIAL> "{" {return new Token(sym.LCBR,yyline);}
<YYINITIAL> "]" {return new Token(sym.RB,yyline);}
<YYINITIAL> ")" {return new Token(sym.RP,yyline);}
<YYINITIAL> "}" {return new Token(sym.RCBR,yyline);}
<YYINITIAL> "length" {return new Token(sym.LENGTH,yyline);}
<YYINITIAL> "new" {return new Token(sym.NEW,yyline);}
<YYINITIAL> "||" {return new Token(sym.LOR,yyline);}
<YYINITIAL> "-" {return new Token(sym.MINUS,yyline);}
<YYINITIAL> "%" {return new Token(sym.MOD,yyline);}
<YYINITIAL> "*" {return new Token(sym.MULTIPLY,yyline);}
<YYINITIAL> "null" {return new Token(sym.NULL,yyline);}
<YYINITIAL> "+" {return new Token(sym.PLUS,yyline);}
<YYINITIAL> "return" {return new Token(sym.RETURN,yyline);}
<YYINITIAL> ";" {return new Token(sym.SEMI,yyline);}
<YYINITIAL> "static" {return new Token(sym.STATIC,yyline);}
<YYINITIAL> "string" {return new Token(sym.STRING,yyline);}
<YYINITIAL> "this" {return new Token(sym.THIS,yyline);}
<YYINITIAL> "true" {return new Token(sym.TRUE,yyline);}
<YYINITIAL> "void" {return new Token(sym.VOID,yyline);}
<YYINITIAL> "while" {return new Token(sym.WHILE,yyline);}

<YYINITIAL> {INTEGER_LITERAL} {
		 try {
		 	int n = Integer.parseInt(yytext()); 
			return new Token(sym.INTEGER,yyline, yytext());
		} catch (Exception e) {
			throw new LexicalError(yyline, yycolumn, yytext());
		} }
<YYINITIAL> {STRING_LITERAL} {return new Token(sym.QUOTE,yyline, yytext());}
<YYINITIAL> {CLASSIDENT} {return new Token(sym.CLASS_ID,yyline, yytext());}
<YYINITIAL> {IDENT} {return new Token(sym.ID,yyline, yytext());}
<YYINITIAL> {WhiteSpace} { }
<YYINITIAL> {IDENT_ILLEGAL} {throw new LexicalError(yyline, yycolumn, yytext());}
<YYINITIAL> {ALL} { throw new LexicalError(yyline, yycolumn, yytext()); }
